{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "深度学习视觉相关的东西经常需要搭建深度学习模型，比如写CNN模型相关代码时，需要借助python图像库来读取图像并进行一系列的图像处理。  \n",
    "图像处理库有很多种，opencv是所有图像库中最全面也最强大的库，常见的图像库如下所示：\n",
    "* opencv\n",
    "* PIL(pillow)\n",
    "* matplotlib.image\n",
    "* scipy.misc\n",
    "* skimage"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 01 opencv图片读取与展示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(547, 730, 3)\n",
      "1197930\n",
      "uint8\n",
      "<class 'numpy.ndarray'>\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import cv2 \n",
    "\n",
    "# Load an image from a file\n",
    "# 文件读取 -> 封装格式解析 -> 数据解码 -> 数据加载\n",
    "img = cv2.imread('image0.jpg', 1) # 0:gray 1:color，默认彩色图\n",
    "\n",
    "# Displays an image in the specified window\n",
    "cv2.imshow('image', img)\n",
    "\n",
    "print(img.shape) # (h,w,c)，检查是灰度图还是彩色图\n",
    "print(img.size) # 像素总数目\n",
    "print(img.dtype) # 数据类型\n",
    "print(type(img)) # numpy矩阵\n",
    "\n",
    "# Waits for a pressed key\n",
    "cv2.waitKey(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "jpg、png等图片格式是文件的压缩封装格式，在这些格式中把文件分为**文件头**（数据的解码信息和附加信息）和**文件数据**（图片经过压缩编码后的数据），解码器根据文件头中的信息对文件数据进行解析还原为原始数据。\n",
    "\n",
    "*注意：图片路径是错的，Opencv也不会报错，print(img) 得到的结果是None。*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 02 opencv图片写入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(547, 730)\n",
      "399310\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import cv2\n",
    "img = cv2.imread('image0.jpg',1)\n",
    "\n",
    "# 彩色图转灰度图\n",
    "gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n",
    "print(gray.shape) # (h,w)\n",
    "print(gray.size)\n",
    "\n",
    "cv2.imwrite('image1.jpg', gray) # img 是解码后的原始图像数据"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 03 opencv图像质量"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "图片编码是为了减小图片的体积，提高压缩比。jpg是有损压缩，png是无损压缩。相比于jpg，png还可以设置透明度alpha。  \n",
    "1M的图片压缩10倍到100k，基本上还可以保证图片质量，但是压缩到10k，图片质量就会严重下降。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import cv2\n",
    "img = cv2.imread('image0.jpg', 1)\n",
    "cv2.imwrite('imageTest.jpg', img, [cv2.IMWRITE_JPEG_QUALITY,50])\n",
    "# cv2.IMWRITE_JPEG_QUALITY 可以描绘jpg图片的质量，质量范围：0-100，0表示压缩比最高，图片质量最低"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1 无损 2 透明度属性\n",
    "import cv2\n",
    "img = cv2.imread('image0.jpg',1)\n",
    "cv2.imwrite('imageTest.png', img, [cv2.IMWRITE_PNG_COMPRESSION,0])\n",
    "# cv2.IMWRITE_PNG_COMPRESSION 可以描绘png图片的压缩比，压缩比范围：0-9，0表示压缩比最低，图片质量最高"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 04 opencv像素操作"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 一个图像中包含很多个像素，每个像素由RGB三个分量组成，对于一个8位颜色深度的图片来说，RGB每个颜色分量的范围为0-255。  \n",
    "* 一个未压缩的原始彩色图片的宽度和高度分别为720和547，则图片大小为：720\\*547\\*3\\*8 bit = 720\\*547\\*3 Byte(字节) = 1.14 M。  \n",
    "* png格式的图片除了RGB三个通道外，还有个表示图片透明度的alpha通道。  \n",
    "* 常见的颜色深度格式除了RGB外，还有BGR。\n",
    "* opencv读进来的图片的颜色通道排列是BGR，而不是RGB，可以用如下方法转为RGB。\n",
    "> cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n",
    " \n",
    "图像坐标系如下：\n",
    "![图像坐标系](图像坐标系.png)\n",
    "u轴表示图像的宽度，对应x；v轴表示图像的高度，对应y。使用**`img[y,x]`**形式对图像矩阵的像素进行操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "39 46 49\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "-1"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import cv2\n",
    "img = cv2.imread('image0.jpg',1)\n",
    "\n",
    "# 读取像素值，img是一个 numpy 矩阵\n",
    "(b,g,r) = img[100,100]\n",
    "print(b,g,r) # bgr\n",
    "\n",
    "# 写入像素值\n",
    "# 从10行100列到110行100列\n",
    "for i in range(1,100):\n",
    "    img[10+i,100] = (255,0,0)\n",
    "cv2.imshow('image',img)\n",
    "cv2.waitKey(0) #1000 ms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 05 拆分及合并图像通道\n",
    "\n",
    "有时需要对RGB三个通道分别操作，这就需要拆分RGB为单个通道，然后需要把独立的通道的图片合成一个RGB。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "img = cv2.imread('image0.jpg',1)\n",
    "\n",
    "r,g,b = cv2.split(img) #拆分\n",
    "img = cv2.merge([r,g,b]) #合并\n",
    "\n",
    "b = img[:,:,0] #拆分b通道\n",
    "\n",
    "# 使红色通道的值都为0，不必拆分再赋值，可以直接使用numpy索引\n",
    "img[:,:,2] = 0"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
